using System;
using System.Text;
using System.Reflection;
using UnityEngine;

namespace KFGame
{
    /// <summary>
    /// 发送数据结构对象
    /// 
    /// </summary>
    public class OutputData
    {

        /// <summary>
        /// 数据结构体在使用中使用到的模式，
        /// 在发送数据到设置时候，通过计算模式进行数据处理
        /// </summary>
        [Flags]
        public enum SendMode : uint
        {
            //一直有效
            alwaysMode = 0x01,
            //持续计时
            timeMode = 0x02,
            //频率计次数
            numberMode = 0x04,
            //合并模式
            combineMode = 0x10,
            //分批次
            oneMode = 0x20,
            //独占发送
            onlyMode = 0x40,
            //回调计数
            callbackMode = 0x80

        }

        //名字
        public string name = "data";

        //标志
        public int tag = 0;

        /// <summary>
        ///发送模式，止参数很重要，决定了数据是否正确发送出去
        ///通常可能需要combineMode 合并其他数据一起发送，才能达到目的
        /// </summary>
        public SendMode mode = SendMode.alwaysMode;

        /// <summary>
        /// SendMode.callbackMode 止模式下有效 
        /// 运行中必需已侦听 DataFiter 的对象，否则计数不正常
        /// 回调名字 配合回调计数使用
        /// </summary>
        public string DataFiterName = "";

        //上机位控制器
        public byte[] userP = new byte[] { 0x01 };

        //上机位数据位置 
        public int userPDataIndex = 2;

        //模板结构数据
        public byte[] tempdats = new byte[24] {0xaa,0x55,0x01,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0xcd
    };

        /// <summary>
        /// 发送的数据
        /// 在发送到设备实制的数据体
        /// </summary>
        private byte[] datas;

        //是否有效
        public bool isEnter = true;


        /// <summary>
        /// 结束时 是否发送结束命令
        /// 实制设置，发送命令时，通过移除数据，设备还在运行
        /// 通过发送结束命令时才能设备正确的工作
        /// </summary>
        public bool isEnd = false;
        /// <summary>
        /// 结束的数据体名字
        /// </summary>
        public string EndDataName = "stop_send";
        /// <summary>
        /// 当前数据发送完比后的结束数据
        /// </summary>
        public OutputData EndData;


        //发送次数据
        public int sendNumber = 0;
        //己发送的次数
        private int currSendNumber = 0;
        //是否发送次数据
        public bool isNumber = false;
        //计次数据是否己开始计算
        private bool isstart = false;




        //开始时间
        private DateTime starttime;
        //持续时间
        public float sustainTime = 0.1f;




        /// <summary>
        /// 添加计数据
        /// </summary>
        /// <param name="a"></param>
        public void addSendNumber(int a)
        {

            sendNumber += a;

            isEnter = true;

        }
        /// <summary>
        /// 实例化 可使用模板数据
        /// </summary>
        /// <param name="template"></param>
        public OutputData(EventModel template = null)
        {
            if (template != null)
                setModel(template);
        }


        /// <summary>
        /// 产生随机字节
        /// </summary>
        /// <returns></returns>
        public static byte getRandom()
        {
            int f = UnityEngine.Random.Range(1, 255);
            return (byte)f;
        }

        /// <summary>
        /// 设置一个发送数据集
        /// </summary>
        /// <param name="data"></param>
        public void setDatas(byte[] data)
        {
            datas = data;

        }

        /// <summary>
        /// 设置一个发送数据 使用字符串
        /// 
        /// </summary>
        /// <param name="data"></param>
        public void setDatas(string data)
        {
            datas = System.Text.Encoding.Default.GetBytes(data);
        }

        /// <summary>
        /// 字符串转成 byte[] 
        /// //16 进制格式string 转byte[]：
        // "3031": 转成 new byte[] { 0x30, 0x31 } 
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        public static byte[] GetBytes(string hexString)
        {
            return Encoding.Default.GetBytes(hexString);
        }

        /// <summary>
        ///  byte[] 转成 16进制字符串
        ///  //byte[] 转16进制格式string：
        // new byte[] { 0x30, 0x31 } 转成 "3031":
        // 0xae00cf => "AE00CF "
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string ToHexString(byte[] bytes)

        {
            string hexString = string.Empty;

            if (bytes == null)
                return hexString;

            StringBuilder strB = new StringBuilder();

            for (int i = 0; i < bytes.Length; i++)
                strB.Append(bytes[i].ToString("X2"));

            hexString = strB.ToString();

            return hexString;
        }

        /// <summary>
        /// 计算时间差
        /// </summary>
        /// <param name="dateBegin"></param>
        /// <param name="dateEnd"></param>
        /// <returns></returns>
        public static Double ExecDateDiff(DateTime dateBegin, DateTime dateEnd)
        {
            TimeSpan ts1 = new TimeSpan(dateBegin.Ticks);
            TimeSpan ts2 = new TimeSpan(dateEnd.Ticks);
            TimeSpan ts3 = ts1.Subtract(ts2).Duration();
            //你想转的格式
            return ts3.TotalSeconds;
        }

        /// <summary>
        /// 合并模式与数据
        /// </summary>
        public void combineDatas()
        {
            datas = (byte[])tempdats.Clone(); 
            for (int a = 0; a < userP.Length; a++)
                datas[userPDataIndex + a] = userP[a];
        }




        /// <summary>
        /// 取出数据 可以用的数据 
        /// </summary>
        /// <returns></returns>
        public byte[] popDatas()
        {
            // 己完成
            if (!isEnter)
                return tempdats;

            //没有初始化
            if (datas == null)
            {
                isEnter = false;
                datas = tempdats;
            }

            //持续发送
            if ((mode & SendMode.alwaysMode) == SendMode.alwaysMode)
                return datas;

            //计次数发送
            if ((((mode & SendMode.numberMode) == SendMode.numberMode)) && (currSendNumber >= sendNumber))
            {
                isEnter = false;
                return tempdats;
            }

            //计次发送
            if (((mode & SendMode.numberMode) == SendMode.numberMode))
            {
                currSendNumber++;
                return datas;
            }

            //计时
            if (((mode & SendMode.timeMode) == SendMode.timeMode))
            {
                //初始化计时器
                if (isstart == false)
                {
                    isstart = true;
                    starttime = DateTime.Now;
                }

                //如果超时  发送内节
                double dd = ExecDateDiff(starttime, DateTime.Now);

                if (dd > sustainTime)
                {
                    isEnter = false;
                    return tempdats;
                }
            }

            return datas;

        }


        public void InitOutData(OutputData data)
        {
            name = data.name;
            tag = data.tag;
            mode = data.mode;
            tempdats = data.tempdats;
            userP = data.userP;
            userPDataIndex = data.userPDataIndex;
            sendNumber = data.sendNumber;
            sustainTime = data.sustainTime;
            currSendNumber = data.currSendNumber;
            isEnter = data.isEnter;
            isstart = data.isstart;
            DataFiterName = data.DataFiterName;


            combineDatas();
        }

        /// <summary>
        /// 使用模板设置数据转成配置
        /// </summary>
        /// <param name="temp"></param>
        public void setModel(EventModel temp)
        {
            name = temp.name;
            tag = temp.tag;
            mode = (SendMode)temp.dataType;
            tempdats = temp.templateData; 
            userP = temp.checkdata;
            userPDataIndex = (int)temp.dataIndex;
            sendNumber = temp.sendnumber;
            sustainTime = (float)temp.sendtime;
            DataFiterName = temp.fiterName;
            isEnd = temp.isEnd;
            EndDataName = temp.EndDataName;
            combineDatas();
        }


        /// <summary>
        /// 回调 callbackMode 模式有效
        /// 配合回调模式和 回调名字使用
        /// </summary>
        /// <param name="df"></param>
        /// <returns></returns>
        public bool onCallBackFiter(DataFiter df)
        {

            if (!isEnter)
                return false;

            if ((mode & SendMode.callbackMode) != SendMode.callbackMode)
                return false;

            if (currSendNumber >= sendNumber)
            {
                isEnter = false;
                return isEnter;
            }
            if (df.name == DataFiterName && df.ischeck)
            {
                if (df.DataInclueCheck())
                {
                    currSendNumber++;
                    if (currSendNumber >= sendNumber)
                    {
                        isEnter = false;
                        return false;
                    }
                    return true;
                }
            }

            return false;
        }


        /// <summary>
        /// 合并数据
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static byte[] mergebytes(byte[] a, byte[] b)
        {
            byte[] ndatas = new byte[a.Length];
            for (int i = 0; i < a.Length; i++)
                ndatas[i] = (byte)(a[i] | b[i]);
            //  ndatas[i] = (byte)((a[i] & b[i]) ^ (a[i] ^ b[i]));
            return ndatas;
        }


    }
}